package org.apache.lucene.store;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;

import joelwilson.GAETestCase;

import org.apache.lucene.store.DatastoreLockFactory.DatastoreLock;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;

public class DatastoreLockFactoryTestCase extends GAETestCase {

	DatastoreLockFactory dslf;
	
	@Before
	public void setUpLockFactory() {
		dslf = new DatastoreLockFactory("unitTest");
	}
	
	@Test
	public void testLockEntityPresence() throws IOException {
		DatastoreLock lock = (DatastoreLock)dslf.makeLock("write.lock");
		lock.obtain();
		
		DatastoreService dss = DatastoreServiceFactory.getDatastoreService();
		PreparedQuery pq = dss.prepare(new Query(GAELuceneConstants.entityKind));
		Entity entity = pq.asSingleEntity();
		assertEquals("Query for EntityKind returns the lock", lock.toString(), entity.getKey().getName());	
	}
	
	@Test
	public void testClearLockWithoutActualLock() throws IOException {
		dslf.clearLock("write.lock");
	}
	
	@Test
	public void testIsLockedAndObtain() throws IOException {
		DatastoreLock lock = (DatastoreLock)dslf.makeLock("write.lock");
		DatastoreLock lock2 = (DatastoreLock)dslf.makeLock("write.lock");
		
		assertFalse("lock.isLocked() == false", lock.isLocked());
		assertFalse("lock2.isLocked() == false", lock2.isLocked());
		
		assertTrue("lock.obtain() == true", lock.obtain());
		assertFalse("lock2.obtain() == false", lock2.obtain());
		
		assertTrue("lock.isLocked() == true", lock.isLocked());
		assertTrue("lock2.isLocked() == true", lock2.isLocked());
		
		lock.release();
		
		assertFalse("lock2.isLocked() == false", lock2.isLocked());
		assertTrue("lock2.obtain() == true", lock2.obtain());
		assertFalse("lock.obtain() == true", lock.obtain());
		
		lock2.release();
	}
	
	@Test
	public void testOtherDirectoriesDoNotCollide() throws IOException {
		DatastoreLockFactory dslf2 = new DatastoreLockFactory("unitTest2");
		DatastoreLock lock = (DatastoreLock)dslf.makeLock("write.lock");
		DatastoreLock lock2 = (DatastoreLock)dslf2.makeLock("write.lock");
		
		assertFalse("lock.isLocked() == false", lock.isLocked());
		assertFalse("lock2.isLocked() == false", lock2.isLocked());
		
		assertTrue("lock.obtain() == true", lock.obtain());
		assertTrue("lock2.obtain() == true", lock2.obtain());
		
		assertTrue("lock.isLocked() == true", lock.isLocked());
		assertTrue("lock2.isLocked() == true", lock2.isLocked());
		
		lock.release();
		lock2.release();
	}

}
